/************************************
 * For msmr 
 * server.c
 * tesing the speed of bufferevent_write
 * 2015-02-03
 * author@tom
************************************/
#include "netLib/client.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>

NetClient *NetClient::pNetClient;

NetClient::NetClient()
{
    pNetClient = this;
#ifdef WIN32
    WORD wdVersion = MAKEWORD(2, 2);//定义自己需要的网络库版本，这里是2.2
	WSADATA wdSockMsg;//这是一个结构体
	int nRes = WSAStartup(wdVersion, &wdSockMsg);//打开一个套接字
#endif
}

void NetClient::recvCb(struct bufferevent *bufevt, void *ctx)
{
    // 从bufferevent中，读取接收到的消息并打印
	auto input = bufferevent_get_input(bufevt);
	int len = evbuffer_get_length(input);
	if( m_recvBuf.size()<len)
	{
		m_recvBuf.resize(len);
	}
    size_t sz = bufferevent_read(bufevt, m_recvBuf.data(), len);
    printf("received bytes: %d\n", sz);
    
    if( m_recvFun )
    {
        (*m_recvFun)(m_recvBuf.data(),sz);
    }
#if 0
    // 按顺序发送pop3指令
    if ( i == 0 ) bufferevent_write(bufevt, "user user1\n", 11);
	
    else if ( i == 1 ) bufferevent_write(bufevt, "pass 12345678\n", 14);
    else if ( i == 2) bufferevent_write(bufevt, "list\n", 5);
    else bufferevent_disable(bufevt, EV_READ);
    i++;
#endif
}

void readCb(struct bufferevent *bufevt, void *ctx)
{
    NetClient::pNetClient->recvCb(bufevt,ctx);
#if 0
    // 按顺序发送pop3指令
    if ( i == 0 ) bufferevent_write(bufevt, "user user1\n", 11);
    else if ( i == 1 ) bufferevent_write(bufevt, "pass 12345678\n", 14);
    else if ( i == 2) bufferevent_write(bufevt, "list\n", 5);
    else bufferevent_disable(bufevt, EV_READ);
    i++;
#endif
}

bool NetClient::init(const std::string &ip,const int nPort)
{
    struct sockaddr_in my_address;
    memset(&my_address, 0, sizeof(my_address));
    my_address.sin_family = AF_INET;
    my_address.sin_addr.s_addr = inet_addr(ip.c_str()); // 127.0.0.1
    my_address.sin_port = htons(nPort);
 
    // build event base
    m_pBase = event_base_new();
 
    // set TCP_NODELAY to let data arrive at the server side quickly
    evutil_socket_t fd;
    fd = socket(AF_INET, SOCK_STREAM, 0);
    m_pConn = bufferevent_socket_new(m_pBase,fd,BEV_OPT_CLOSE_ON_FREE);
    evutil_make_socket_nonblocking(fd);
    //if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&enable, sizeof(enable)) < 0)
    //   printf("ERROR: TCP_NODELAY SETTING ERROR!\n");
    bufferevent_setcb(m_pConn, readCb, NULL, NULL, NULL);
    bufferevent_enable(m_pConn, EV_WRITE|EV_READ);
    printf("ready connect\n");
    if(bufferevent_socket_connect(m_pConn,(struct sockaddr*)&my_address,sizeof(my_address)) == 0)
    {
            printf("connect success\n");
            return true;
    }
    else
    {
        printf("connect failed!");
        return false;
    }
}

void NetClient::send(const char *pMesg,int nSize)
{
    bufferevent_write(m_pConn,pMesg,nSize);
    
    struct evbuffer* output = bufferevent_get_output(m_pConn);
    int len = 0;
    len = evbuffer_get_length(output);
    printf("output buffer has %d bytes left\n", len);
}

void NetClient::loop()
{
    event_base_dispatch(m_pBase);
}

void NetClient::disconnect()
{
    bufferevent_free(m_pConn);
    event_base_free(m_pBase);
}

void NetClient::setRecvCb(RecvFun *pRecvCb)
{
    m_recvFun = pRecvCb;
}